/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Comunicacion;

import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 *
 * @author julian
 */
public class Parsear {
    private static final String ESPAÑOL = "spa";
    private static final String NOMBRE_IMAGEN = "miImagen.jpg";
    private static final String SALIDA_IMAGEN = "resultImagen";
    private static final String ABBYY = "AbbyyOCR.jar";
    private static final String IMAGEN_AGREGAR = "agregar.jpg";
    private static final String TESSERACT = "tesseract.exe";
    
    //RUTA A CAMBIAR SEGÚN LA UBICACIÓN DEL PROYECTO
    private static final String RUTA_PROYECTO = "C:\\Users\\julian\\Desktop\\Pr3Legados\\Practica3\\";
    
    private static final String TESSERACT_PATH = "\"C:/Program Files (x86)/Tesseract-OCR/tesseract\"";
    private static final String IMAGEN_PATH = RUTA_PROYECTO + NOMBRE_IMAGEN;
    private static final String SALIDA_IMAGEN_PATH = RUTA_PROYECTO + SALIDA_IMAGEN;
    private static final String ABBYY_PATH = RUTA_PROYECTO + ABBYY;
    private static final String IMAGEN_AGREGAR_PATH = RUTA_PROYECTO + IMAGEN_AGREGAR;

    private static final String COMPROBADOR_NUM_REGISTROS = "OMTIEME";
    private static final String COMPROBADOR_DATOS = "DIME";
    private static final String COMPROB_PROGCINTA_LINEA_CAMPOS = "CINTA";
    private static final String COMPROB_PROGCINTA_LINEA_SALIR = "PARA";

    /**
     * Parsea de una imagen el número de registros que hay en el DOSBox
     * @param captura imagen a parsear
     * @return el número de registros del DOSBox
     */
    public static String registros(BufferedImage captura) {
        BufferedReader bfString = obtenerBfStringTesseract(captura);

        String sCadena = "";
        try {
            while ((sCadena = bfString.readLine()) != null) {
                if (sCadena.contains(COMPROBADOR_NUM_REGISTROS)) {
                    StringTokenizer tokens = new StringTokenizer(sCadena);
                    String aux;
                    while (tokens.hasMoreTokens()) {
                        if (tokens.nextToken().contains(COMPROBADOR_NUM_REGISTROS)) {
                            return tokens.nextToken();
                        }
                    }
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
        }

        return "";
    }

    /**
     * Parsea de una imagen los datos de un programa que hay en el DOSBox
     * @param captura imagen a parsear
     * @param nomPrograma nombre del programa del cual se quiere obtener 
     * sus datos
     * @return los datos del programa
     */
    public static String datosDeUnPrograma(BufferedImage captura, String nomPrograma) {
        BufferedReader bfString = obtenerBfStringTesseract(captura);
        String sCadena = "";
        try {
            while ((sCadena = bfString.readLine()) != null) {
                if (sCadena.contains(COMPROBADOR_DATOS)) {
                    return "";
                }

                if (sCadena.contains(nomPrograma)) {
                    return sCadena;
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "";

    }

    /**
     * Parsea de una imagen los programas de una cinta que hay en el DOSBox
     * @param captura imagen a parsear 
     * @param nombreCinta nombre de la cinta de la cual se quiere obtener
     * sus programas
     * @param datos lista donde se introducirán los programas de esa cinta 
     * @return si hay más programas de esa cinta en la pantalla siguiente
     */
    public static boolean datosDeUnaCinta(BufferedImage captura, String nombreCinta, ArrayList<String> datos) {
        BufferedReader bfString = obtenerBfStringAbbyy(captura);
        String sCadena = "";
        String cinta = "";
        String cintaAnterior = "";
        boolean result = true;

        try {
            while ((sCadena = bfString.readLine()) != null) {
                String[] campos = sCadena.split("\\s+");
                int longitud = campos.length;
                if (longitud >= 2) {
                    //cogemos el penúltimo campo que es el de la cinta  
                    cintaAnterior = cinta;
                    cinta = campos[longitud - 2];

                    //con el "PARA" se elimina la linea de "PULSE ESPACE PARA CONTINUAR U OTRA TECLA PARA ACABAR"
                    //con el "CINTA" se elimina la linea de "Nº NOMBRE TIPO CINTA REGISTRO"
                    if (cinta.contains(nombreCinta) && !cinta.contains(COMPROB_PROGCINTA_LINEA_SALIR) && !cinta.contains(COMPROB_PROGCINTA_LINEA_CAMPOS)) {
                        datos.add(sCadena);
                    }
                }
            }
            if (!cintaAnterior.contains(nombreCinta)) {
                return false;
            }
        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
            result = false;
        }
        return result;
    }

    /**
     * Obtiene BufferedReader de una imagen sobre la que se ha hecho OCR con
     * Tesseract
     * @param captura imagen sobre la que se hace OCR
     * @return BufferedReader
     */
    private static BufferedReader obtenerBfStringTesseract(BufferedImage captura) {
        Process process = null;
        FileReader fr = null;
        BufferedReader bf = null;

        try {
            //guarda la imagen
            File file = new File(NOMBRE_IMAGEN);
            ImageIO.write(captura, "jpg", file);

            //lanza el proceso Tesseract 
            process = Runtime.getRuntime().exec(new String[]{TESSERACT, NOMBRE_IMAGEN, SALIDA_IMAGEN, "-l", ESPAÑOL});

            //espera a que termine Tesseract
            try {
                process.waitFor();
            } catch (InterruptedException ex) {
                Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
            }

            fr = new FileReader(SALIDA_IMAGEN + ".txt");
            bf = new BufferedReader(fr);
            return bf;

        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
        }
        return bf;
    }

    /**
     * Obtiene BufferedReader de una imagen sobre la que se ha hecho OCR con
     * Abbyy
     * @param captura imagen sobre la que se hace OCR
     * @return 
     */
    private static BufferedReader obtenerBfStringAbbyy(BufferedImage captura) {
        Process process = null;
        FileReader fr = null;
        BufferedReader bf = null;

        try {
            BufferedImage img = modificarImagen(captura);
            //guarda la imagen
            File file = new File(IMAGEN_PATH);
//            File file = new File(NOMBRE_IMAGEN);
            ImageIO.write(img, "jpg", file);

            //lanza el proceso AbbyyOCR
            process = Runtime.getRuntime().exec("java -jar " + ABBYY_PATH + " recognize " + IMAGEN_PATH + " " + SALIDA_IMAGEN_PATH + ".txt --lang=Spanish");
//            process = Runtime.getRuntime().exec("java -jar " + ABBYY + " recognize " + NOMBRE_IMAGEN + " " + SALIDA_IMAGEN + ".txt --lang=Spanish");

            //espera a que termine AbbyyOCR
            try {
                process.waitFor();
            } catch (InterruptedException ex) {
                Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
            }

            //lee el fichero de salida generado por Tesseract
            fr = new FileReader(SALIDA_IMAGEN_PATH + ".txt");
//            fr = new FileReader(SALIDA_IMAGEN + ".txt");
            bf = new BufferedReader(fr);
            return bf;

        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
        }
        return bf;
    }

    /**
     * Método que une la imagen pasada por parámetro con una iamgen prediseña.
     * La imagen resultante es la pasada por parámetro unida horizontalmente con
     * la prediseñada, la imagen prediseña quedará en la parte derecha.
     *
     * @param captura imagen a unir con la imagen prediseñada.
     * @return
     */
    private static BufferedImage modificarImagen(BufferedImage captura) {
        File file2 = new File(IMAGEN_AGREGAR_PATH);
//        File file2 = new File(IMAGEN_AGREGAR);

        BufferedImage img2 = null;
        try {
            img2 = ImageIO.read(file2);
        } catch (IOException ex) {
            Logger.getLogger(Parsear.class.getName()).log(Level.SEVERE, null, ex);
        }

        int widthImg1 = captura.getWidth();
        int heightImg1 = captura.getHeight();

        int widthImg2 = img2.getWidth();

        BufferedImage img = new BufferedImage(
                widthImg1 + widthImg2, // Final image will have width and height as
                heightImg1, // addition of widths and heights of the images we already have
                BufferedImage.TYPE_INT_RGB);

        img.createGraphics().drawImage(captura, 0, 0, null); // 0, 0 are the x and y positions
        img.createGraphics().drawImage(img2, widthImg1, 0, null);

        return img;
    }
}
